const express = require("express");
const mysql = require("mysql");
const fs = require("fs");
const { log } = require("console");
// const bodyParser = require('body-parser');
const app = express();
var tokenList = [];
app.use("/public", express.static("public"));
// app.get('/', function (req, res) {
//   res.redirect('/public/index.html')
// });
app.use(function (req, res, next) {
  console.log(req.path);
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "*");
  var index = tokenList.indexOf(req.headers.token);
  const whiteList = ["/upload", "/login"];
  if (!whiteList.includes(req.path) && index === -1) {
    return res.send({ code: 403, msg: "token错误" });
  }
  if (!whiteList.includes(req.path) && index !== -1) {
    var date = getToken(req.headers.token).date;
    if (Date.now() - date > 86400000 * 2) {
      return res.send({ code: 403, msg: "token过期" });
    }
  }
  next();
});
// app.use(bodyParser.json({limit: '1mb'}));
// app.use(bodyParser.urlencoded({extended: true}));

var connection;
// connection.end()
// mysql 8小时无程序执行，自动断开连接
function connect() {
  connection = mysql.createConnection({
    host: "localhost",
    user: "root",
    password: "root123456",
    database: "library",
  });
  connection.connect();
  connection.on("error", function (err) {
    if (err.code === "PROTOCOL_CONNECTION_LOST") {
      connect();
    }
  });
}
connect();

function getTime() {
  var date = new Date();
  var year = date.getFullYear();
  var month = date.getMonth() + 1;
  var day = date.getDate();
  var h = date.getHours();
  var m = date.getMinutes();
  var s = date.getSeconds();
  month < 10 && (month = "0" + month);
  day < 10 && (day = "0" + day);
  h < 10 && (h = "0" + h);
  m < 10 && (m = "0" + m);
  s < 10 && (s = "0" + s);
  return `${year}-${month}-${day} ${h}:${m}:${s}`;
}
function setToken(id, type) {
  var date = new Date();
  var year = date.getFullYear() + "";
  var month = date.getMonth() + 1;
  var day = date.getDate();
  month < 10 && (month = "0" + month);
  day < 10 && (day = "0" + day);
  year = year.slice(2);
  var token = `${id}-${type}-${year}${month}${day}`;
  return Buffer.from(token).toString("base64");
}
function getToken(token) {
  token = Buffer.from(token, "base64").toString();
  token = token.split("-");
  return {
    id: token[0],
    type: token[1],
    date: new Date(
      `20${token[2].slice(0, 2)}-${token[2].slice(2, 4)}-${token[2].slice(4)}`
    ).getTime(),
  };
}
app.get("/create", function (req, res) {
  var obj = req.query;
  obj.date = getTime();
  connection.query(
    "INSERT INTO books(name,author,price,publisher,introduction,cover,date,total,stock,recommend) VALUES(?,?,?,?,?,?,?,?,?,?)",
    [
      obj.name,
      obj.author,
      obj.price,
      obj.publisher,
      obj.introduction,
      obj.cover,
      obj.date,
      obj.total,
      obj.total,
      0,
    ],
    function (err, rows) {
      res.send(rows);
    }
  );
});
app.get("/deleteBook", function (req, res) {
  var id = req.query.id;
  connection.query(`DELETE FROM books where id=${id}`, function (err, rows) {
    res.send(rows);
  });
});
app.get("/update", function (req, res) {
  var obj = req.query;
  obj.date = getTime();
  connection.query(
    `UPDATE books SET name = ?,author = ?,price = ?,publisher = ?,introduction = ?,cover = ?,date = ?,total = ? WHERE Id = ?`,
    [
      obj.name,
      obj.author,
      obj.price,
      obj.publisher,
      obj.introduction,
      obj.cover,
      obj.date,
      obj.total,
      obj.id,
    ],
    function (err, rows) {
      res.send(rows);
    }
  );
});
app.get("/search", function (req, res) {
  var query = req.query;
  // var count = 2;
  // var obj = {};
  var sql = "";
  if (query.name && query.author) {
    sql = ` where name="${query.name}" and author="${query.author}"`;
  } else if (query.name) {
    sql = ` where name="${query.name}"`;
  } else if (query.author) {
    sql = ` where author="${query.author}"`;
  }

  const recordP = new Promise((resolve, reject) => {
    connection.query(`select * from record`, function (err, rows) {
      resolve(rows.length);
    });
  });
  const booksP = new Promise((resolve, reject) => {
    connection.query(
      `select * from books${sql} order by id desc limit ${
        (query.current - 1) * query.pageSize
      },${query.pageSize}`,
      function (err, books) {
        let dataLen = books.length;
        books.map((v) => {
          v.recordNum = 0;
          let sql = ` where bookId="${v.id}"`;
          connection.query(`select * from record${sql}`, function (err, rows) {
            dataLen--;
            v.recordNum = rows.length;
            if (dataLen === 0) {
              resolve(books);
            }
          });
        });
      }
    );
  });

  const countP = new Promise((resolve, reject) => {
    connection.query(
      `select count(*) as total from books${sql}`,
      function (err, rows) {
        // obj.total = rows[0].total;
        resolve(rows[0].total);
        // !count && res.send(obj);
      }
    );
  });
  Promise.all([recordP, booksP, countP]).then((data) => {
    let obj = {
      pa: data[0],
      data: data[1],
      total: data[2],
    };
    res.send(obj);
  });
});
app.get("/getUser", function (req, res) {
  var query = req.query;
  var count = 2;
  var obj = {};
  var sql = "";
  if (query.username) {
    sql = ` where username="${query.username}"`;
  }
  connection.query(
    `select id,username,type,avatar,nickname from user${sql} order by id desc limit ${
      (query.current - 1) * query.pageSize
    },${query.pageSize}`,
    function (err, rows) {
      count--;
      obj.data = rows;
      !count && res.send(obj);
    }
  );
  connection.query(
    `select count(*) as total from user${sql}`,
    function (err, rows) {
      count--;
      obj.total = rows[0].total;
      !count && res.send(obj);
    }
  );
});
app.get("/updateUser", function (req, res) {
  var obj = req.query;
  var token = getToken(req.headers.token).id;
  connection.query(
    `UPDATE user SET avatar = ?,nickname = ?,password = ? WHERE Id = ?`,
    [obj.avatar, obj.nickname, obj.password, token],
    function (err, rows) {
      connection.query(
        `UPDATE comment SET avatar = ?,nickname = ? WHERE userId = ?`,
        [obj.avatar, obj.nickname, token],
        function (err, rows) {
          console.log("回调", err, rows);
          res.send(rows);
        }
      );
    }
  );
});
app.get("/login", function (req, res) {
  var obj = req.query;
  var token = "";
  connection.query(
    `select * from user where username="${obj.username}"`,
    function (err, rows) {
      if (!rows?.length) {
        if (!/^1[3456789]\d{9}$/.test(obj.username)) {
          return res.send({ code: 1, msg: "请用手机号登录" });
        }
        obj.date = getTime();
        connection.query(
          "INSERT INTO user(username,password,type,avatar,nickname,date) VALUES(?,?,?,?,?,?)",
          [obj.username, obj.password, "1", "default.png", "", obj.date],
          function (err, rows) {
            token = setToken(rows?.insertId, "1");
            tokenList.push(token);
            res.send({
              code: 0,
              msg: "注册成功",
              token,
              id: rows?.insertId,
              type: "1",
              nickname: "同学",
              username: obj.username,
              avatar: "default.png",
            });
          }
        );
        return;
      }
      rows = rows[0];
      if (rows.password !== obj.password) {
        return res.send({ code: 1, msg: "密码错误" });
      }
      token = setToken(rows.id, rows.type);
      tokenList.push(token);
      res.send({
        code: 0,
        msg: "登录成功",
        token,
        id: rows.id,
        type: rows.type,
        nickname: rows.nickname,
        username: rows.username,
        avatar: rows.avatar,
      });
    }
  );
});
app.get("/getRecord", function (req, res) {
  var query = req.query;
  var count = 2;
  var obj = {};
  var sql = "";
  if (query.book && query.user) {
    sql = ` where book="${query.book}" and user="${query.user}"`;
  } else if (query.book) {
    sql = ` where book="${query.book}"`;
  } else if (query.user) {
    sql = ` where user="${query.user}"`;
  }
  connection.query(
    `select * from record${sql} order by id desc limit ${
      (query.current - 1) * query.pageSize
    },${query.pageSize}`,
    function (err, rows) {
      count--;
      obj.data = rows;
      !count && res.send(obj);
    }
  );
  connection.query(
    `select count(*) as total from record${sql}`,
    function (err, rows) {
      count--;
      obj.total = rows[0].total;
      !count && res.send(obj);
    }
  );
});
app.get("/getRecordId", function (req, res) {
  var query = req.query;
  var obj = {};
  connection.query(
    `select bookId from record where user="${query.user}" and type=1`,
    function (err, rows) {
      obj.data = rows.map((v) => v.bookId);
      obj.total = rows.length;
      res.send(obj);
    }
  );
});
app.get("/getComment", function (req, res) {
  var query = req.query;
  var count = 2;
  var obj = {};
  connection.query(
    `select * from comment order by id desc limit ${
      (query.current - 1) * query.pageSize
    },${query.pageSize}`,
    function (err, rows) {
      count--;
      obj.data = rows;
      !count && res.send(obj);
    }
  );
  connection.query(
    `select count(*) as total from comment`,
    function (err, rows) {
      count--;
      obj.total = rows[0].total;
      !count && res.send(obj);
    }
  );
});
app.get("/addComment", function (req, res) {
  var obj = req.query;
  obj.date = getTime();
  obj.userId = getToken(req.headers.token).id;
  connection.query(
    "INSERT INTO comment(userId,avatar,nickname,content,date) VALUES(?,?,?,?,?)",
    [obj.userId, obj.avatar, obj.nickname, obj.content, obj.date],
    function (err, rows) {
      res.send(rows);
    }
  );
});
app.get("/deleteComment", function (req, res) {
  var id = req.query.id;
  connection.query(`DELETE FROM comment where id=${id}`, function (err, rows) {
    res.send(rows);
  });
});
app.get("/updateRecord", function (req, res) {
  var obj = req.query;
  connection.query(
    `select stock from books where id=${obj.bookId}`,
    function (err, rows) {
      var stock = +rows[0].stock + 1;
      console.log(stock);
      connection.query(
        `UPDATE books SET stock=${stock} WHERE id = ${obj.bookId}`,
        function (err, rows) {
          connection.query(
            `UPDATE record SET type = 0,updateTime = ? WHERE Id = ?`,
            [getTime(), obj.id],
            function (err, rows) {
              res.send(rows);
            }
          );
        }
      );
    }
  );
});
app.get("/addRecord", function (req, res) {
  var obj = req.query;
  var token = getToken(req.headers.token);
  connection.query(
    `select stock from books where id=${obj.bookId}`,
    function (err, rows) {
      var stock = rows[0].stock - 1;
      connection.query(
        `UPDATE books SET stock=${stock} WHERE id = ${obj.bookId}`,
        function (err, rows) {
          connection.query(
            "INSERT INTO record(book,user,bookId,userId,type,createTime) VALUES(?,?,?,?,?,?)",
            [obj.book, obj.user, obj.bookId, token.id, "1", getTime()],
            function (err, rows) {
              res.send(rows);
            }
          );
        }
      );
    }
  );
});

app.get("/addRecommend", function (req, res) {
  var obj = req.query;
  var token = getToken(req.headers.token);
  connection.query(
    `select recommend from books where id=${obj.bookId}`,
    function (err, rows) {
      var recommend = Number(rows[0].recommend) + 1;
      connection.query(
        `UPDATE books SET recommend=${recommend} WHERE id = ${obj.bookId}`,
        function (err, rows) {
          connection.query(
            "INSERT INTO record(book,user,bookId,userId,type,createTime) VALUES(?,?,?,?,?,?)",
            [obj.book, obj.user, obj.bookId, token.id, "1", getTime()],
            function (err, rows) {
              res.send(rows);
            }
          );
        }
      );
    }
  );
});

app.get("/getRecommend", function (req, res) {
  var query = req.query;
  var count = 2;
  var obj = {
    welcome: null,
    recommended: null,
  };
  connection.query(`select * from books`, function (err, rows) {
    count--;
    let recommend = rows.sort((a, b) => b.recommend - a.recommend)[0];
    obj.recommended = recommend;
    !count && res.send(obj);
  });
  connection.query(`select * from books`, function (err, books) {
    let dataLen = books.length;
    books.map((v) => {
      let sql = ` where bookId="${v.id}"`;
      connection.query(`select * from record${sql}`, function (err, rows) {
        dataLen--;
        v.recordNum = rows.length;
        if (dataLen === 0) {
          let welcome = books.sort((a, b) => b.recordNum - a.recordNum)[0];
          obj.welcome = welcome;
          count--;
          !count && res.send(obj);
        }
      });
    });
  });
});

app.post("/upload", function (req, res) {
  //新建一个空数组接受流的信息
  var chunks = [];
  //获取长度
  let num = 0;
  req.on("data", function (chunk) {
    chunks.push(chunk);
    num += chunk.length;
  });
  req.on("end", function () {
    //最终流的内容本体
    var buffer = Buffer.concat(chunks, num);
    //新建数组接收出去\r\n的数据下标
    let rems = [];
    //根据\r\n分离数据和报头
    for (var i = 0; i < buffer.length; i++) {
      let v = buffer[i];
      let v2 = buffer[i + 1];
      // 10代表\n 13代表\r
      if (v === 13 && v2 === 10) {
        rems.push(i);
      }
    }
    //获取上传图片信息
    let picmsg_1 = buffer.slice(rems[0] + 2, rems[1]).toString();
    let filename = picmsg_1.match(/filename=".*"/g)[0].split('"')[1];
    console.log(filename);
    //图片数据
    var nbuf = buffer.slice(rems[3] + 2, rems[rems.length - 2]);
    let address = Date.now() + filename.slice(filename.indexOf("."));
    //创建空文件并写入内容
    fs.writeFile("./public/pic/" + address, nbuf, function (err) {
      if (err) {
        console.log(err);
      } else {
        console.log("success");
      }
    });
    res.send({ name: filename, path: address });
  });
});

app.listen(88, (res) => {
  console.log("服务启动成功");
});
